package tests;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.junit.Test;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.TreeMultimap;

import reit.main.*;
import reit.xml.customer.CustomersGroups;
import reit.xml.customer.CustomersGroups.CustomerGroups;
import reit.xml.repairdetail.AssetContentsRepairDetails.AssetContent.Materials.Material;


public class ParserTest {

	@Test
	public void testCreateClerks() {
		//test that clerkDetails were added to container
		List<ClerkDetails> toTest = Parser.CreateClerks("src/xmls/InitialData.xml");
		Iterator<ClerkDetails> clerkIterator = toTest.iterator();
		ClerkDetails clerkUnderTest = clerkIterator.next();
		
		assertEquals("Ken Harush",clerkUnderTest.getName());
		assertEquals(3.0, clerkUnderTest.getLocation().getX().byteValue(),0);
		assertEquals(3.0, clerkUnderTest.getLocation().getY().byteValue(),0);
		
		clerkUnderTest = clerkIterator.next();
		assertEquals("Paula Bitton",clerkUnderTest.getName());
		assertEquals(3.0, clerkUnderTest.getLocation().getX().byteValue(),0);
		assertEquals(3.0, clerkUnderTest.getLocation().getY().byteValue(),0);
		
		clerkUnderTest = clerkIterator.next();
		assertEquals("Wolfgang Eisenkott",clerkUnderTest.getName());
		assertEquals(3.0, clerkUnderTest.getLocation().getX().byteValue(),0);
		assertEquals(3.0, clerkUnderTest.getLocation().getY().byteValue(),0);
		
		clerkUnderTest = clerkIterator.next();
		assertEquals("Paula Die",clerkUnderTest.getName());
		assertEquals(3.0, clerkUnderTest.getLocation().getX().byteValue(),0);
		assertEquals(3.0, clerkUnderTest.getLocation().getY().byteValue(),0);

	}


	@Test
	public void testCreateRepairMaterials() {
		Hashtable<String,RepairObjectInterface> toTest = Parser.CreateRepairMaterials("src/xmls/InitialData.xml");

		assertEquals("Nails",toTest.get("Nails").getName());
		assertEquals(5000,toTest.get("Nails").getQuantity());

		assertEquals("Carpet Cleaner",toTest.get("Carpet Cleaner").getName());
		assertEquals(5000,toTest.get("Carpet Cleaner").getQuantity());

		assertEquals("Screws",toTest.get("Screws").getName());
		assertEquals(5000,toTest.get("Screws").getQuantity());

		assertEquals("Kitchen Cleaner",toTest.get("Kitchen Cleaner").getName());
		assertEquals(2000,toTest.get("Kitchen Cleaner").getQuantity());

		assertEquals("Glass Cleaner",toTest.get("Glass Cleaner").getName());
		assertEquals(1500,toTest.get("Glass Cleaner").getQuantity());

		assertEquals("Disinfectant",toTest.get("Disinfectant").getName());
		assertEquals(1500,toTest.get("Disinfectant").getQuantity());

		assertEquals("Floor Cleaner",toTest.get("Floor Cleaner").getName());
		assertEquals(1500,toTest.get("Floor Cleaner").getQuantity());

		assertEquals("Trash Bag",toTest.get("Trash Bag").getName());
		assertEquals(2500,toTest.get("Trash Bag").getQuantity());

		assertEquals("Paper Towel",toTest.get("Paper Towel").getName());
		assertEquals(1500,toTest.get("Paper Towel").getQuantity());

		assertEquals("Bathroom Cleaner",toTest.get("Bathroom Cleaner").getName());
		assertEquals(150,toTest.get("Bathroom Cleaner").getQuantity());

		assertEquals("Laundry Cleaner",toTest.get("Laundry Cleaner").getName());
		assertEquals(2500,toTest.get("Laundry Cleaner").getQuantity());

		assertEquals("Cleaning Pads",toTest.get("Cleaning Pads").getName());
		assertEquals(2500,toTest.get("Cleaning Pads").getQuantity());

		assertEquals("Sand Cloth",toTest.get("Sand Cloth").getName());
		assertEquals(2500,toTest.get("Sand Cloth").getQuantity());

	}

	@Test
	public void testCreateRepairTools() {
		Hashtable<String,RepairObjectInterface> toTest = Parser.CreateRepairTools("src/xmls/InitialData.xml");

		assertEquals("Vacuum Cleaner",toTest.get("Vacuum Cleaner").getName());
		assertEquals(3,toTest.get("Vacuum Cleaner").getQuantity());

		assertEquals("Hammer",toTest.get("Hammer").getName());
		assertEquals(5,toTest.get("Hammer").getQuantity());

		assertEquals("Jackhammer",toTest.get("Jackhammer").getName());
		assertEquals(2,toTest.get("Jackhammer").getQuantity());

		assertEquals("Jacksaw",toTest.get("Jacksaw").getName());
		assertEquals(4,toTest.get("Jacksaw").getQuantity());

		assertEquals("Hammer",toTest.get("Hammer").getName());
		assertEquals(5,toTest.get("Hammer").getQuantity());

		assertEquals("Drill",toTest.get("Drill").getName());
		assertEquals(7,toTest.get("Drill").getQuantity());

		assertEquals("Screw Driver",toTest.get("Screw Driver").getName());
		assertEquals(5,toTest.get("Screw Driver").getQuantity());

		assertEquals("Adjustable Spanner",toTest.get("Adjustable Spanner").getName());
		assertEquals(5,toTest.get("Adjustable Spanner").getQuantity());

		assertEquals("Knife",toTest.get("Knife").getName());
		assertEquals(5,toTest.get("Knife").getQuantity());

		assertEquals("Pliers",toTest.get("Pliers").getName());
		assertEquals(5,toTest.get("Pliers").getQuantity());
	}

	@Test
	public void testGetNumberOfMaintenancePersons() {
		assertEquals(3,Parser.getNumberOfMaintenancePersons("src/xmls/InitialData.xml"));
	}

	@Test
	public void testGetNumberOfRentalRequests() {
		assertEquals(15,Parser.getNumberOfRentalRequests("src/xmls/InitialData.xml"));
	}

	@Test
	public void testCreateCustomerGroupDetails() {
		List<CustomerGroupDetails> toTest = Parser.CreateCustomerGroupDetails("src/xmls/CustomersGroups.xml");

		CustomerGroupDetails group1 = toTest.get(0);
		CustomerGroupDetails group2 = toTest.get(1);
		assertNotNull(group1);
		assertEquals("Group 1", group1.getGroupManagerName());
		assertEquals("Group 2", group2.getGroupManagerName());

		Iterator<Customer>group1It = group1.getCustomers().iterator();
		Customer tmpc = group1It.next();
		System.out.println(tmpc.getName());
		assertEquals(10,tmpc.getDmgPercent(),10);

		tmpc = group1It.next();
		assertEquals("Customer 2",tmpc.getName());
		assertEquals(5,tmpc.getDmgPercent(),0);

		tmpc = group1It.next();
		assertEquals("Customer 3",tmpc.getName());
		assertEquals(5,tmpc.getDmgPercent(),0);

		Iterator<Customer>group2It = group2.getCustomers().iterator();
		Customer tmpc2 = group2It.next();
		assertEquals(3,tmpc2.getDmgPercent(),0);

		tmpc2 = group2It.next();

		assertEquals("Customer 2",tmpc2.getName());
		assertEquals(0.5,tmpc2.getDmgPercent(),0);

		tmpc2 = group2It.next();
		assertEquals("Customer 3",tmpc2.getName());
		assertEquals(0.5,tmpc2.getDmgPercent(),0);

		tmpc2 = group2It.next();
		assertEquals("Customer 4",tmpc2.getName());
		assertEquals(0.5,tmpc2.getDmgPercent(),0);

		//TODO: add tests here for rentalrequsts..
		List<CustomerGroupDetails> toTestRentalRequsts = Parser.CreateCustomerGroupDetails("src/xmls/CustomersGroups.xml");
		group1 = toTest.get(0);
		group2 = toTest.get(1);

		Iterator<RentalRequest> andreiIt =group1.getRentalRequests().iterator();
		RentalRequest tmprq = andreiIt.next();
		assertEquals(new Byte((byte) 1),tmprq.getId());
		assertEquals(3,tmprq.getRoomSize(),0);
		assertEquals("Apartment",tmprq.getType());
		assertEquals(5,tmprq.getDuration(),0);

		tmprq = andreiIt.next();
		assertEquals(new Byte((byte) 2),tmprq.getId());
		assertEquals(3,tmprq.getRoomSize(),0);
		assertEquals("Hut",tmprq.getType());
		assertEquals(3,tmprq.getDuration(),0);

		Iterator<RentalRequest> meniIt = group2.getRentalRequests().iterator();
		tmprq = meniIt.next();
		assertEquals(new Byte((byte) 3),tmprq.getId());
		assertEquals(5,tmprq.getRoomSize(),0);
		assertEquals("Cottage",tmprq.getType());
		assertEquals(2,tmprq.getDuration(),0);

		tmprq = meniIt.next();tmprq = meniIt.next();
		assertEquals(new Byte((byte) 5),tmprq.getId());
		assertEquals(5,tmprq.getRoomSize(),0);
		assertEquals("Cottage",tmprq.getType());
		assertEquals(1,tmprq.getDuration(),0);
	}

	@Test
	//testing createAssets by testing its called functions becuase it dont do much :P
	public void testCreateAssets() {
		String path = "src/xmls/Assets.xml";
		reit.xml.assets.Assets assets = null;
		try{
			JAXBContext jc = JAXBContext.newInstance(reit.xml.assets.Assets.class);
			Unmarshaller um = jc.createUnmarshaller();
			JAXBElement<reit.xml.assets.Assets> root = um.unmarshal(new StreamSource(path), reit.xml.assets.Assets.class); // creating a JAXBelement to store Assets no @XMLRootElement forces to do this from xml and putting value in assets
			assets  =  root.getValue();
		}
		catch (Exception e){
			System.out.println(e.getMessage());
		} 
		HashMap<String, ArrayListMultimap<Integer, Pair<AtomicBoolean, Asset>>> assetContainer = Parser.createAssetContainer(assets);

		List<Pair<AtomicBoolean, Asset>> tmpal = assetContainer.get("Apartment").get(3);
		Asset tmpa = tmpal.iterator().next().getSecond();
		System.out.println("tmpa" + tmpa);
		assertEquals("Asset 1",tmpa.getName());
		assertEquals(3,tmpa.getSize(),0);
		assertEquals(100,tmpa.getCostPerNight(),0);
		assertTrue(tmpa.getLocation().equals(new Location(20.0,20.0)));
		assertTrue(tmpa.getAssetContents().containsKey("TV"));
		assertTrue(tmpa.getAssetContents().containsKey("Bed"));
		assertTrue(tmpa.getAssetContents().containsKey("Fridge"));
		assertTrue(tmpa.getAssetContents().containsKey("Desk"));
		assertTrue(tmpa.getAssetContents().containsKey("Stove"));

		tmpal = assetContainer.get("Cottage").get(5);

		tmpa = tmpal.iterator().next().getSecond();
		assertEquals("Asset 5",tmpa.getName());
		assertEquals(5,tmpa.getSize(),0);
		assertEquals(new Location(12.0,16.0),tmpa.getLocation());
		assertEquals(120,tmpa.getCostPerNight(),0);
		assertTrue(tmpa.getAssetContents().containsKey("TV"));
		assertTrue(tmpa.getAssetContents().containsKey("Bed"));
		assertTrue(tmpa.getAssetContents().containsKey("Fridge"));
		assertTrue(tmpa.getAssetContents().containsKey("Desk"));
		assertTrue(tmpa.getAssetContents().containsKey("Stove"));

	}

	@Test
	public void testAssetContentsRepairMaterialDetails() {

		String path = "src/xmls/AssetContentsRepairDetails.xml";
		Hashtable<String, RepairMaterialInformation> toTest = Parser.createAssetContentsRepairMaterialDetails(path);
		reit.xml.repairdetail.AssetContentsRepairDetails assetContentRepairDetails = null;
		try{
			JAXBContext jc = JAXBContext.newInstance(reit.xml.repairdetail.AssetContentsRepairDetails.class);
			Unmarshaller um = jc.createUnmarshaller();
			JAXBElement<reit.xml.repairdetail.AssetContentsRepairDetails> root = um.unmarshal(new StreamSource( // creating a JAXBelement to store Assets no @XMLRootElement forces to do this from xml and putting value in assets
					path), reit.xml.repairdetail.AssetContentsRepairDetails.class);
			assetContentRepairDetails  =  root.getValue();
		}
		catch (Exception e){
			System.out.println(e.getMessage());
		}
		for (reit.xml.repairdetail.AssetContentsRepairDetails.AssetContent a :assetContentRepairDetails.getAssetContent() ){
			assertTrue(toTest.containsKey(a.getName()));
			RepairMaterialInformation tmpAC = toTest.get(a.getName());
			for (int i = 0; i < a.getMaterials().getMaterial().size(); i++){
				assertEquals((a.getMaterials().getMaterial().get(i)).getName(),tmpAC.getMaterials().get(i).getName());
				assertEquals(a.getMaterials().getMaterial().get(i).getQuantity() , tmpAC.getMaterials().get(i).getQuantity(),0);
			}
		}
	}

	@Test
	public void testAssetContentsRepairToolDetails() {
		Hashtable<String, RepairToolInformation> toTest = Parser.createAssetContentsRepairToolDetails("src/xmls/AssetContentsRepairDetails.xml");
		String path = "src/xmls/AssetContentsRepairDetails.xml";
		reit.xml.repairdetail.AssetContentsRepairDetails assetContentRepairDetails = null;
		try{
			JAXBContext jc = JAXBContext.newInstance(reit.xml.repairdetail.AssetContentsRepairDetails.class);
			Unmarshaller um = jc.createUnmarshaller();
			JAXBElement<reit.xml.repairdetail.AssetContentsRepairDetails> root = um.unmarshal(new StreamSource( // creating a JAXBelement to store Assets no @XMLRootElement forces to do this from xml and putting value in assets
					path), reit.xml.repairdetail.AssetContentsRepairDetails.class);
			assetContentRepairDetails  =  root.getValue();
		}
		catch (Exception e){
			System.out.println(e.getMessage());
		}
		for (reit.xml.repairdetail.AssetContentsRepairDetails.AssetContent a :assetContentRepairDetails.getAssetContent() ){
			assertTrue(toTest.containsKey(a.getName()));
			RepairToolInformation tmpRC = toTest.get(a.getName());
			for (int i = 0; i < a.getMaterials().getMaterial().size(); i++){
				assertEquals((a.getTools().getTool().get(i)).getName(),tmpRC.getTools().get(i).getName());
				assertEquals((a.getTools().getTool().get(i)).getQuantity() , tmpRC.getTools().get(i).getQuantity(),0);
			}
		}
	}


}
